﻿using System.Reflection;
using System.Reflection.Emit;
using System;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;

// Author: Miroslav Matula m.matula@alutam.cz 
// Date : 9.9.2010
namespace Slma.OData.Factory
{
	public static partial class ClassFactory
	{
    public static void CopyAttribute(PropertyInfo property_, PropertyBuilder propertyBuilder_, out bool validate_)
    {
      validate_ = false;
      object[] atrs = property_.GetCustomAttributes(true);
      foreach(var atr in atrs) {
        CustomAttributeBuilder cb = null;
        Type typeAtt = atr.GetType();
        var pis = new List<PropertyInfo>();
        var pvs = new List<object>();

        //-- Validační Attribut  ------------------
        var vatr = atr as ValidationAttribute;
        if(vatr != null) {
          validate_ = true;
          if(!string.IsNullOrEmpty(vatr.ErrorMessage)) {
            pis.Add(typeAtt.GetProperty("ErrorMessage"));
            pvs.Add(vatr.ErrorMessage);
          }
          if(!string.IsNullOrEmpty(vatr.ErrorMessageResourceName)) {
            pis.Add(typeAtt.GetProperty("ErrorMessageResourceName"));
            pvs.Add(vatr.ErrorMessageResourceName);
          }
          if(vatr.ErrorMessageResourceType != null) {
            pis.Add(typeAtt.GetProperty("ErrorMessageResourceType"));
            pvs.Add(vatr.ErrorMessageResourceType);
          }
        }
        //-- Vytvoř CustomAttribute ----------------- 
        switch(typeAtt.Name) {
          #region ValidationAttributes
          case "CustomValidationAttribute": {
            var la = atr as CustomValidationAttribute;
            cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { typeof(Type), typeof(Int32) }),
              new object[] { la.ValidatorType, la.Method }, pis.ToArray(), pvs.ToArray());
          } break;
          case "StringLengthAttribute": {
            var la = atr as StringLengthAttribute;
            if(la.MinimumLength > 0) {
              pis.Add(typeAtt.GetProperty("MinimumLength"));
              pvs.Add(la.MinimumLength);
            }
            cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { typeof(Int32) }), new object[] { la.MaximumLength }, pis.ToArray(), pvs.ToArray());
          } break;
          case "RequiredAttribute": {
            var la = atr as RequiredAttribute;
            if(la.AllowEmptyStrings) {
              pis.Add(typeAtt.GetProperty("AllowEmptyStrings"));
              pvs.Add(la.AllowEmptyStrings);
            }
            cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { }), new object[] { }, pis.ToArray(), pvs.ToArray());
          } break;
          case "RegularExpressionAttribute": {
            var la = atr as RegularExpressionAttribute;
            cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { typeof(string) }), new object[] { la.Pattern }, pis.ToArray(), pvs.ToArray());
          } break;
          case "RangeAttribute": {
            var la = atr as RangeAttribute;
            if(la.Minimum is Int32) {
              cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { typeof(Int32), typeof(Int32) }),
                new object[] { la.Minimum, la.Maximum }, pis.ToArray(), pvs.ToArray());
            } else if(la.Minimum is Double) {
              cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { typeof(Double), typeof(Double) }),
                new object[] { la.Minimum, la.Maximum }, pis.ToArray(), pvs.ToArray());
            } else if(la.Minimum is string) {
              cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { typeof(Type), typeof(Double), typeof(Double) }),
                new object[] { la.OperandType, la.Minimum, la.Maximum }, pis.ToArray(), pvs.ToArray());
            }
          } break;

          #endregion
          #region Display Attributes
          case "DisplayAttribute": {
            var la = atr as DisplayAttribute;
            if(la.ResourceType != null) {
              pis.Add(typeAtt.GetProperty("ResourceType"));
              pvs.Add(la.ResourceType);
            }
            if(!string.IsNullOrEmpty(la.GroupName)) {
              pis.Add(typeAtt.GetProperty("GroupName"));
              pvs.Add(la.GroupName);
            }
            if(!string.IsNullOrEmpty(la.Name)) {
              pis.Add(typeAtt.GetProperty("Name"));
              pvs.Add(la.Name);
            }
            if(la.GetOrder() != null) {
              pis.Add(typeAtt.GetProperty("Order"));
              pvs.Add(la.Order);
            }
            if(!string.IsNullOrEmpty(la.Prompt)) {
              pis.Add(typeAtt.GetProperty("Prompt"));
              pvs.Add(la.Prompt);
            }
            if(!string.IsNullOrEmpty(la.ShortName)) {
              pis.Add(typeAtt.GetProperty("ShortName"));
              pvs.Add(la.ShortName);
            }
            if(!string.IsNullOrEmpty(la.Description)) {
              pis.Add(typeAtt.GetProperty("Description"));
              pvs.Add(la.Description);
            }
            if(la.GetAutoGenerateField() != null) {
              pis.Add(typeAtt.GetProperty("AutoGenerateField"));
              pvs.Add(la.AutoGenerateField);
            }
            if(la.GetAutoGenerateFilter() != null) {
              pis.Add(typeAtt.GetProperty("AutoGenerateFilter"));
              pvs.Add(la.AutoGenerateFilter);
            }
            cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { }), new object[] { }, pis.ToArray(), pvs.ToArray());
          } break;
          case "DisplayColumnAttribute": {
            var la = atr as DisplayColumnAttribute;
            if(!string.IsNullOrEmpty(la.SortColumn)) {
              pis.Add(typeAtt.GetProperty("SortColumn"));
              pvs.Add(la.SortColumn);
            }
            if(la.SortDescending) {
              pis.Add(typeAtt.GetProperty("SortDescending"));
              pvs.Add(la.SortDescending);
            }
            cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { typeof(string) }), new object[] { la.DisplayColumn }, pis.ToArray(), pvs.ToArray());
          } break;
          case "DisplayFormatAttribute": {
            var la = atr as DisplayFormatAttribute;
            if(!string.IsNullOrEmpty(la.DataFormatString)) {
              pis.Add(typeAtt.GetProperty("DataFormatString"));
              pvs.Add(la.DataFormatString);
            }
            if(!string.IsNullOrEmpty(la.NullDisplayText)) {
              pis.Add(typeAtt.GetProperty("NullDisplayText"));
              pvs.Add(la.NullDisplayText);
            }
            if(la.ApplyFormatInEditMode) {
              pis.Add(typeAtt.GetProperty("ApplyFormatInEditMode"));
              pvs.Add(la.ApplyFormatInEditMode);
            }
            if(la.ConvertEmptyStringToNull) {
              pis.Add(typeAtt.GetProperty("ConvertEmptyStringToNull"));
              pvs.Add(la.ConvertEmptyStringToNull);
            }
            cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { }), new object[] { }, pis.ToArray(), pvs.ToArray());
          } break;

          #endregion
          case "KeyAttribute": {
            var la = atr as KeyAttribute;
            cb = new CustomAttributeBuilder(typeAtt.GetConstructor(new Type[] { }), new object[] { }, pis.ToArray(), pvs.ToArray());
          } break;
        }
        //-- Přidej attribut -----------
        if(cb != null) {
          propertyBuilder_.SetCustomAttribute(cb);
        }
      }
    }
  }
}
